package types

import (
	"net/http"

	"github.com/zeromicro/go-zero/core/mapping"
	"github.com/zeromicro/go-zero/rest/httpx"
)

// 错误码定义
const (
	// 成功
	Success = 0

	// 客户端错误
	ErrInvalidParams  = 10001
	ErrUnauthorized   = 10002
	ErrForbidden      = 10003
	ErrNotFound       = 10004
	ErrMethodNotAllow = 10005
	ErrTooManyRequest = 10006

	// 服务端错误
	ErrInternalServer = 20001
	ErrDatabase       = 20002
	ErrCache          = 20003

	// 业务错误
	ErrUserAlreadyExists = 30001
	ErrUserNotFound      = 30002
	ErrInvalidPassword   = 30003
	ErrPasswordEncrypt   = 30004
	ErrTokenInvalid      = 30005
	ErrTokenExpired      = 30006
)

// 错误码描述
var codeMessages = map[int]string{
	Success:              "成功",
	ErrInvalidParams:     "请求参数错误",
	ErrUnauthorized:      "未登录或授权失败",
	ErrForbidden:         "权限不足",
	ErrNotFound:          "资源不存在",
	ErrMethodNotAllow:    "请求方法不允许",
	ErrTooManyRequest:    "请求过于频繁",
	ErrInternalServer:    "服务器内部错误",
	ErrDatabase:          "数据库操作失败",
	ErrCache:             "缓存操作失败",
	ErrUserAlreadyExists: "用户已存在",
	ErrUserNotFound:      "用户不存在",
	ErrInvalidPassword:   "密码错误",
	ErrPasswordEncrypt:   "密码加密失败",
	ErrTokenInvalid:      "无效的令牌",
	ErrTokenExpired:      "令牌已过期",
}

// CodeMessage 获取错误码对应的消息
func CodeMessage(code int) string {
	if msg, ok := codeMessages[code]; ok {
		return msg
	}
	return "未知错误"
}

// 标准API响应
type Response struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Data    interface{} `json:"data,omitempty"`
}

// NewSuccessResponse 创建成功响应
func NewSuccessResponse(data interface{}) *Response {
	return &Response{
		Code:    Success,
		Message: CodeMessage(Success),
		Data:    data,
	}
}

// NewErrorResponse 创建错误响应
func NewErrorResponse(code int) *Response {
	return &Response{
		Code:    code,
		Message: CodeMessage(code),
	}
}

// NewErrorResponseWithMsg 创建带自定义消息的错误响应
func NewErrorResponseWithMsg(code int, msg string) *Response {
	return &Response{
		Code:    code,
		Message: msg,
	}
}

// 自定义HTTP错误处理函数
func ErrorHandler(err error) (int, interface{}) {
	switch e := err.(type) {
	case *mapping.ApiError:
		return http.StatusBadRequest, NewErrorResponse(ErrInvalidParams)
	case *ValidateError:
		return http.StatusBadRequest, NewErrorResponseWithMsg(ErrInvalidParams, e.Error())
	case *httpx.CodeError:
		return http.StatusOK, NewErrorResponse(e.Code)
	default:
		return http.StatusInternalServerError, NewErrorResponse(ErrInternalServer)
	}
}

// ValidateError 验证错误
type ValidateError struct {
	Message string
}

func (e *ValidateError) Error() string {
	return e.Message
}

// NewValidateError 创建验证错误
func NewValidateError(msg string) *ValidateError {
	return &ValidateError{Message: msg}
}
